﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using daDataLayer;
using daStaticAnalyser;
using daSyntaxAnalyser.SyntaxTree;
using CQLQueries.Analyzers;

namespace CQLQueries
{
    public class CQL_Interpreter
    {
        // шаблон "одиночка"
        private static CQL_Interpreter instance;

        /// <summary>
        /// Единственный экземпляр класса контроллера
        /// </summary>
        public static CQL_Interpreter Instance
        {
            get
            {
                if (instance == null)
                    instance = new CQL_Interpreter();
                return instance;
            }
        }

        public event EventHandler<MsgArg> MsgEvent;

        public CQL_Interpreter()
        {
            SyntaxTreeVisitor.Instance.VisitEvent += new EventHandler<SyntaxTreeArgs>(Execute);
            TreeStackVal = new Stack<object>();
        }

        public List<Object> Rezult;

        public Stack<object> TreeStackVal;
        public QueryData ТекущийЗапрос;
        private int ii;
        public bool ExecuteQuery(String Query, List<String> FileNames)
        {
            Distinct = false;
            Rezult = new List<object>();
            if (!CQL_SA.Instance.Translate(Query)) return false;
            FileController.Instance.Clear();
            foreach (String s in FileNames)
            {
                FileController.Instance.Add(s);
            }
            ii = 1;
            foreach(QueryData z in CQL_Semantic.Instance.Запросы)
            {
                ТекущийЗапрос = z;
                List<FileElement> roots = StaticAnalyserController.Instance.Analyse(FileController.Instance.FileNames, false);
                if (t1)
                {
                    SendMsg("Запрос №" + ii.ToString() + " выполнен", ТекущийЗапрос.Begin, ТекущийЗапрос.End);
                }
                else t1 = true;
                ++ii;
                if (roots == null) return true;
            }
            return Rezult != null;
        }

        public event EventHandler<ErrorArgs> ErrorOccuredEvent;
        private void ErrorExecute(String message)
        {
            if (ErrorOccuredEvent != null)
                ErrorOccuredEvent(this, new ErrorArgs(message,
                    CQL_LA.Instance.CurPos - CQL_LA.Instance.CurText.Length,
                    "Ошибка выполнения CQL-запроса", -1, -1));
        }

        private void SendMsg(string str, int beg, int end)
        {
            if (MsgEvent != null) MsgEvent(this, new MsgArg(str, beg, end));    
        }

        public Type own;
        public Object ownval;
        private void Execute(object sender, SyntaxTreeArgs e)
        {
            ownval = e.Element;
            own = e.Element.GetType();
            t1 = true;
            if (ОбходСинтаксическогоДерева(e.Element))
            {
                if (Distinct)
                {
                    if (Rezult.Exists(s => s.ToString() == ТекущийЗапрос.КореньДерева.NodeTree.ToString()))
                    {
                        return;
                    }
                }
                Rezult.Add(ТекущийЗапрос.КореньДерева.NodeTree);
            }
        }

        public bool Distinct;

        public void GetAllVals(Type seltype, Object obj1)
        {
            if (!ТекущийЗапрос.GetValParams(seltype, obj1))
            {
                t1 = false;
            }
        }

        public bool t1;
        private bool ОбходСинтаксическогоДерева(ISyntaxTreeElement owner)
        {
            ТекущийЗапрос.КореньДерева.NodeTree = owner;
            ТекущийЗапрос.КореньДерева.Visit();
            return (bool)ТекущийЗапрос.КореньДерева.ValueUp;
        }       

    }
}
